﻿using System.Net.NetworkInformation;
using Core.Combat.Data;
using Core.Combat.FlyerObj;
using UnityEngine;

namespace Core.Combat.CoreModule
{
    public class BulletBehaviourCoreModule : BulletCoreModuleBase
    {
        public BulletBehaviourCoreData BCoreData => BaseBullet.BulletData.behaviourCoreData;
        public Vector3 flyDirection;
        
        public BulletBehaviourCoreModule(Bullet obj) : base(obj)
        {
        }

        public Collider2D CurrentTarget => _traceTarget;
        
        #region Main Methods

        public override void InitState()
        {
            base.InitState();
            flyDirection = CtrlObj.up;
            _traceTarget = null;
            splitCount = BCoreData.splitNumber;
            _delaySplitTimer = BCoreData.delaySplitTime;
            reboundCount = BCoreData.reboundsNumber == 0 ? 0 : BCoreData.reboundsNumber + 1;
            penetrateCount = BCoreData.penetrateNumber;
        }

        public override void Update()
        {
            base.Update();
            TraceHandle();
            DelaySpitHandle();
        }

        public override void FixedUpdate()
        {
            base.FixedUpdate();
            ControlFly();
        }
        
        #endregion

        private void ControlFly()
        {
            CtrlObj.position += flyDirection * (BaseBullet.BulletData.flyingSpeed * Time.fixedDeltaTime);
        }

        #region Override Methods

        public override void OnBulletHit(Collider2D collider)
        {
            if (collider == null)
                return;
            ReboundHandle(collider);
            PenetrateHandle(collider);
            SplitHandle(collider);
            
            BulletHitResultHandle(collider);
        }

        public override void OnBulletDataOverride(Bullet.BulletDataPipeline dataPipeline)
        {
            splitCount = dataPipeline.splitCount;
        }

        /// <summary>
        /// 子弹击中的结果处理
        /// </summary>
        /// <param name="collider"></param>
        private void BulletHitResultHandle(Collider2D collider)
        {
            if (!BaseBullet.CanHit(collider))
            {
                if (reboundCount > 1)
                    return;
                BaseBullet.Stop();
            }
            else
            {
                if (penetrateCount > 0 || splitCount > 0) 
                    return;
                
                BaseBullet.Stop();
            }
        }

        #endregion

        #region Behaviour Core Methods

        #region 追踪

        private Collider2D _traceTarget = null;
        // private Vector2 _curTraceVelocity;
        private float _lastCheckTraceTargetTime;
        private void TraceHandle()
        {
            if (BCoreData.traceIntensity <= 0)
                return;
            
            if (_traceTarget == null)
            {
                if (Time.time > _lastCheckTraceTargetTime + 0.2f)
                {
                    var target = GetTraceTarget();
                    _traceTarget = target;
                    _lastCheckTraceTargetTime = Time.time;
                }
            }

            if (_traceTarget != null)
            {
                // 期望方向
                Vector2 desireDirection = (_traceTarget.transform.position - CtrlObj.position).normalized;
    
                // 如果方向很接近了，就直接锁定方向
                if (Mathf.Approximately(Vector2.Dot(desireDirection, flyDirection), 1f))
                    flyDirection = desireDirection;
                
                // 当前与期望方向的插值
                flyDirection = Vector2.Lerp(flyDirection, desireDirection, BCoreData.traceIntensity * Time.deltaTime);
            }
        }

        private Collider2D GetTraceTarget()
        {
            if (CtrlObj == null)
                return null;
            return CtrlObj.TryGetNearestTarget(BCoreData.traceRange,
                BaseBullet.AttackObject.hitProperties.hitLayer, BaseBullet.AttackObject.hitProperties.blockLayer);
        }

        #endregion

        #region 反弹

        public int reboundCount;
        private void ReboundHandle(Collider2D collider)
        {
            if (BCoreData.reboundsNumber <= 0)
                return;
            
            if (TryRebound(collider))
            {
                RaycastHit2D hitInfo;
                if (BaseBullet.OpenHitCheckOpt)
                {
                    hitInfo = BaseBullet.hitCheckResult;
                    if (hitInfo.collider)
                    {
                        flyDirection = CalcReboundDirection(hitInfo.normal);
                        reboundCount--;
                    }
                }
                else
                {
                    hitInfo = Physics2D.Raycast(CtrlObj.position, flyDirection, 1f, BaseBullet.AttackObject.hitProperties.blockLayer);
                    if (hitInfo.collider)
                    {
                        flyDirection = CalcReboundDirection(hitInfo.normal);
                        reboundCount--;
                    }
                }
            }
        }

        private Vector2 CalcReboundDirection(Vector2 normal)
        {
            Vector2 inDir = flyDirection + -(flyDirection * 0.5f);
            Vector2 outDir = Vector2.Reflect(inDir, normal).normalized;
            // float inAngle = Vector2.Angle(flyDirection, normal);
            // outDir = Quaternion.AngleAxis(Mathf.Lerp(0, -(90 - inAngle), BCoreData.reboundAsthenia),
            //     Vector3.forward) * outDir;
            return outDir;
        }

        private bool TryRebound(Collider2D collider)
        {
            if (reboundCount < 0)
                return false;
            // 判断是否是墙壁，是可击中目标且不是可阻拦目标，就不能进行反弹
            // 反之，不是可击中的，且可阻拦的，可反弹
            if (BaseBullet.CanHit(collider) 
                && !BaseBullet.AttackObject.hitProperties.blockLayer.IsInLayer(collider.gameObject.layer))
                return false;
            return true;
        }
        
        #endregion

        #region 穿透

        public int penetrateCount;
        // public bool CanPenetrate => penetrateCount > 0;
        private void PenetrateHandle(Collider2D collider)
        {
            if (BCoreData.penetrateNumber <= 0)
                return;

            if (TryPenetrate(collider))
            {
                penetrateCount--;
            }
            else
            {
                penetrateCount = 0;
            }
        }

        private bool TryPenetrate(Collider2D collider)
        {
            if (penetrateCount <= 0 || collider == null)
                return false;

            return BaseBullet.CanHit(collider);
        }

        #endregion

        #region 分裂

        public int splitCount;
        private float _delaySplitTimer;
        private void SplitHandle(Collider2D collider)
        {
            if (BCoreData.splitNumber <= 0)
                return;

            if(splitCount <= 0)
                return;
            
            if (BCoreData.isPostHitSplit
                && TryHitSplit(collider))
            {
                SplitBullet();
            }
            else
            {
                splitCount = 0;
            }
        }

        private bool TryHitSplit(Collider2D collider)
        {
            return BaseBullet.CanHit(collider);
        }

        private void DelaySpitHandle()
        {
            if (BCoreData.splitNumber <=0 
                || BCoreData.isPostHitSplit)
                return;

            if (splitCount <= 0)
                return;
            
            _delaySplitTimer -= Time.deltaTime;
            if (_delaySplitTimer <= 0)
            {
                // 进行分裂
                SplitBullet();
            }
        }

        private void SplitBullet()
        {
            splitCount--;
            float splitAngle = 20f;
            Vector2 splitDir1 = Quaternion.AngleAxis(-splitAngle, Vector3.forward) * flyDirection;
            Vector2 splitDir2 = Quaternion.AngleAxis(splitAngle, Vector3.forward) * flyDirection;

            // 新New
            var b = BaseBullet.Generator.CreateBullet(CtrlObj.position,
                         splitDir1, BaseBullet.BulletData);
            b.BulletDataOverride(new Bullet.BulletDataPipeline
            {
                splitCount = this.splitCount
            });

            flyDirection = splitDir2;
            _delaySplitTimer = BCoreData.delaySplitTime;

            // for (int i = -splitNum / 2; i < splitNum / 2; i++)
            // {
            //     if (i == 0)
            //     {
            //         if (splitNum % 2 == 0)
            //             i++;
            //     }
            //     float angle = BaseBullet.BulletData.fireCoreData.scatterAngle * i;
            //     Vector2 splitDir = Quaternion.AngleAxis(angle, Vector3.forward) * flyDirection;
            //     if (i != 0)
            //     {
            //         var b = BaseBullet.Generator.CreateBullet(CtrlObj.position,
            //             splitDir, BaseBullet.BulletData);
            //         b.bulletDataPipeline.splitCount = splitCount;
            //     }
            //     else
            //     {
            //         flyDirection = splitDir;
            //     }
            // }
        }

        #endregion
        
        #endregion
        
    }
}